<script setup lang="ts">
import {
  NButton,
  NCard,
  NForm,
  NFormItem,
  NInput,
  NPopconfirm,
  useMessage,
  useModal,
  NTag,
  NNumberAnimation,
  NTree,
  NSpace,
  NSpin,
  NScrollbar,
  type DataTableColumns,
  type FormRules,
  type FormInst,
  type TreeOption,
  type PaginationProps
} from 'naive-ui'
import { reactive, ref, h, computed } from 'vue'

import * as roleApi from '@/api/role'
import { ScrollContainer, DynamicList } from '@/components'
import { useInjection } from '@/composables'
import { useComponentThemeOverrides } from '@/composables/useComponentThemeOverrides'
import { mediaQueryInjectionKey } from '@/injection'
import { toRefsUserStore } from '@/stores'

import type { Role, RoleQuery, Permission } from '@/api/role'

// 定义 TreeData 类型
interface TreeData extends TreeOption {
  key: string
  label: string
  value: string
  children?: TreeData[]
  disabled?: boolean
}

const { isMaxMd, isMaxLg } = useInjection(mediaQueryInjectionKey)

const message = useMessage()
const modal = useModal()

const { scrollbarInMainLayout } = useComponentThemeOverrides()

// 表格数据和分页
const dataList = ref<Role[]>([])
const isRequestLoading = ref(false)
const checkedRowKeys = ref<Array<string>>([])

// 分页配置
const pagination = reactive<PaginationProps>({
  page: 1,
  pageSize: 10,
  showSizePicker: true,
  pageSizes: [10, 20, 50, 100],
  itemCount: 0,
  showQuickJumper: true,
  onUpdatePage: (page: number) => {
    pagination.page = page
    getDataList()
  },
  onUpdatePageSize: (pageSize: number) => {
    pagination.pageSize = pageSize
    pagination.page = 1
    getDataList()
  },
})

// 搜索表单
const searchForm = reactive<RoleQuery>({
  keyword: '',
})

// 新增/编辑表单
const formRef = ref<FormInst | null>(null)
const form = reactive<Omit<Role, 'id' | 'createdAt' | 'updatedAt'>>({
  name: '',
  description: '',
  permissions: [],
})

const rules: FormRules = {
  name: {
    required: true,
    message: '请输入角色名称',
  },
}

// 获取登录用户信息
const { user } = toRefsUserStore()

// 权限数据
const permissions = ref<Permission[]>([])
const rolePermissions = ref<string[]>([])
const isLoadingPermissions = ref(false)

// 权限树数据（用于分配权限模态框）
const permissionTreeData = ref<TreeData[]>([])
const checkedKeys = ref<string[]>([])
const searchKeyword = ref('')
const assignPermissionRoleId = ref<string>('')
const assignPermissionRoleName = ref<string>('')

// 过滤后的权限树
const filteredTreeData = computed(() => {
  if (!searchKeyword.value.trim()) {
    return permissionTreeData.value
  }

  const keyword = searchKeyword.value.toLowerCase()

  function filterTree(tree: TreeData[]): TreeData[] {
    return tree
      .map(item => {
        const filteredChildren = item.children ? filterTree(item.children) : []
        const itemMatches = item.label?.toLowerCase().includes(keyword)
        const hasMatchingChildren = filteredChildren.length > 0

        if (itemMatches || hasMatchingChildren) {
          return {
            ...item,
            children: filteredChildren.length > 0 ? filteredChildren : undefined,
            // 确保匹配的节点默认展开
            expanded: true
          }
        }
        return null
      })
      .filter(Boolean) as TreeData[]
  }

  return filterTree(permissionTreeData.value)
})

// 统计数据
const roleStats = reactive({
  total: 0,
  withPermissions: 0,
  withoutPermissions: 0,
})

// 操作列折叠状态
const isActionsExpanded = ref(false)

// 获取角色列表
async function getDataList() {
  isRequestLoading.value = true
  try {
    const params: RoleQuery = {
      page: pagination.page,
      pageSize: pagination.pageSize,
      keyword: searchForm.keyword,
    }
    const res = await roleApi.getRoles(params)
    // 根据mock API的响应格式调整数据访问方式
    dataList.value = res.list || []
    pagination.itemCount = res.total

    // 更新统计数据
    roleStats.total = res.total
    roleStats.withPermissions = res.list.filter((role: Role) => role.permissions.length > 0).length
    roleStats.withoutPermissions = res.list.filter(
      (role: Role) => role.permissions.length === 0,
    ).length
  } catch {
    message.error('获取角色列表失败')
  } finally {
    isRequestLoading.value = false
  }
}

// 获取权限列表
async function getPermissionList() {
  isLoadingPermissions.value = true
  try {
    const res = await roleApi.getPermissions()
    // 根据mock API的响应格式调整数据访问方式
    permissions.value = res
  } catch {
    message.error('获取权限列表失败')
  } finally {
    isLoadingPermissions.value = false
  }
}

// 打开新增/编辑模态框
let currentRoleId: string | null = null
function openModal(role?: Role) {
  // 重置表单
  form.name = ''
  form.description = ''
  form.permissions = []

  currentRoleId = role?.id || null

  if (role) {
    // 编辑模式，填充表单数据
    form.name = role.name
    form.description = role.description
    form.permissions = role.permissions
  }

  const title = role ? '编辑角色' : '新增角色'

  modal.create({
    autoFocus: false,
    title,
    preset: 'dialog',
    draggable: true,
    style: {
      width: '500px',
      ...(isMaxMd.value ? { marginInline: '16px' } : {}),
    },
    positiveText: '保存',
    negativeText: '取消',
    content: () => {
      return h('div', [
        h(
          NForm,
          {
            ref: formRef,
            model: form,
            rules: rules,
            labelPlacement: 'left',
            labelWidth: 80,
          },
          [
            h(NFormItem, { label: '角色名称', path: 'name' }, [
              h(NInput, {
                value: form.name,
                'onUpdate:value': (value: string) => (form.name = value),
                clearable: true,
                placeholder: '请输入角色名称',
              }),
            ]),
            h(NFormItem, { label: '角色描述', path: 'description' }, [
              h(NInput, {
                value: form.description,
                'onUpdate:value': (value: string) => (form.description = value),
                clearable: true,
                placeholder: '请输入角色描述',
                type: 'textarea',
                rows: 3,
              }),
            ]),
          ],
        ),
      ])
    },
    onPositiveClick: async () => {
      const valid = await formRef.value?.validate()
      if (valid) {
        // 准备保存的数据，确保格式正确
        const saveData = {
          name: form.name,
          description: form.description,
          permissions: form.permissions
        }
        if (currentRoleId) {
          // 编辑角色
          try {
            await roleApi.updateRole(currentRoleId, saveData)
            message.success('角色更新成功')
            getDataList()
            modal.destroyAll()
          } catch {
              message.error('角色更新失败')
            }
        } else {
          // 新增角色
          try {
            await roleApi.createRole(saveData)
            message.success('角色创建成功')
            getDataList()
            modal.destroyAll()
          } catch {
               message.error('角色创建失败')
            }
        }
      }
    },
    onNegativeClick: () => {
      modal.destroyAll()
    },
  })
}

// 删除角色
async function deleteRoleHandler(id: string) {
  try {
    await roleApi.deleteRole(id)
    message.success('角色删除成功')
    getDataList()
  } catch {
    message.error('角色删除失败')
  }
}

// 批量删除角色
async function batchDeleteHandler() {
  if (checkedRowKeys.value.length === 0) {
    message.warning('请选择要删除的角色')
    return
  }

  try {
    await roleApi.batchDeleteRoles(checkedRowKeys.value)
    message.success('批量删除成功')
    getDataList()
    checkedRowKeys.value = []
  } catch {
    message.error('批量删除失败')
  }
}

// 分配权限
async function assignPermissionHandler(roleId: string, roleName: string) {
  // 保存当前角色信息
  assignPermissionRoleId.value = roleId
  assignPermissionRoleName.value = roleName

  // 获取最新的权限列表和角色已分配的权限
  try {
    isLoadingPermissions.value = true
    // 同时获取权限列表和角色权限
    const [newPermissions, newRolePermissions] = await Promise.all([
      roleApi.getPermissions(),
      roleApi.getRolePermissions(roleId)
    ])
    // 更新权限列表
    permissions.value = newPermissions
    rolePermissions.value = newRolePermissions
  } catch {
    message.error('获取权限数据失败')
    isLoadingPermissions.value = false
    return
  }

  function convertPermissionsToTree(permissions: Permission[], parentId?: string): TreeData[] {
    // 获取登录用户的权限
    const userPermissions = user.value?.permissions || []
    
    // 递归检查节点是否应该显示
    function shouldShowNode(permissionId: number): boolean {
      // 如果用户有权限管理该节点，或者该节点有子节点应该显示，则显示该节点
      return userPermissions.includes(permissionId) || 
             permissions.some(p => p.pid === permissionId && shouldShowNode(p.id))
    }
    
    return permissions
      .filter((permission) => {
        // 处理根节点（pid 不存在或为 0）和子节点
        if (parentId === undefined) {
          return (permission.pid === undefined || permission.pid === 0) && shouldShowNode(permission.id)
        }
        return permission.pid?.toString() === parentId && shouldShowNode(permission.id)
      })
      .map((permission) => {
        const children = convertPermissionsToTree(permissions, permission.id.toString())
        // 检查当前节点是否允许编辑（用户必须直接拥有该权限）
        const canEdit = userPermissions.includes(permission.id)
        return {
          key: permission.id.toString(),
          label: permission.name,
          value: permission.id.toString(),
          children: children.length > 0 ? children : undefined,
          disabled: !canEdit, // 用户没有该权限时，节点不可编辑
        }
      })
  }

  // 转换权限为树结构并更新全局变量
  permissionTreeData.value = convertPermissionsToTree(permissions.value)
  searchKeyword.value = '' // 重置搜索关键词
  isLoadingPermissions.value = false // 数据加载完成，重置加载状态

  modal.create({
    // 在模态框打开后设置checkedKeys，确保权限树组件已渲染
    onAfterEnter: () => {
      checkedKeys.value = [...rolePermissions.value]
    },
    autoFocus: false,
    title: `分配权限 - ${assignPermissionRoleName.value}`,
    preset: 'dialog',
    draggable: true,
    closeOnEsc: true,
    style: {
      width: '768px',
      maxWidth: '95vw',
      height: '600px',
      ...(isMaxMd.value ? { width: '95vw', height: '80vh' } : {}),
    },
    positiveText: '确定',
    negativeText: '取消',
    content: () => {
      return h('div', { class: 'flex flex-col h-full min-h-0' }, [
        // 搜索和统计区域
        h('div', {
          class: 'p-4 flex flex-col sm:flex-row gap-4 items-start sm:items-center justify-between'
        }, [
          // 搜索框
          h(NInput, {
            placeholder: '搜索权限名称...',
            clearable: true,
            value: searchKeyword.value,
            onInput: (value: string) => {
              searchKeyword.value = value
            },
            size: 'medium',
            prefix: () => h('span', { class: 'iconify ph--magnifying-glass text-gray-400' }),
            class: 'w-full sm:w-auto flex-1 sm:max-w-md'
          }),

          // 统计和操作按钮
          h('div', { class: 'flex items-center gap-3 w-full sm:w-auto justify-between sm:justify-end flex-wrap' }, [
            // 已选权限统计
            h('div', {
              key: checkedKeys.value.length,
              class: 'text-sm bg-gray-50 dark:bg-gray-750 px-3 py-1 rounded-full'
            }, `${checkedKeys.value.length} 个权限已选择`),

            // 操作按钮组
            h('div', { class: 'flex gap-2' }, [
              h(NButton,
                {
                  type: isAllSelected.value ? 'default' : 'primary',
                  size: 'small',
                  onClick: toggleSelectAll,
                  disabled: isLoadingPermissions.value
                },
                {
                  icon: () => h('span', {
                    class: `iconify ${isAllSelected.value ? 'ph--x-square' : 'ph--check-square'}`
                  }),
                  default: () => isAllSelected.value ? '取消' : '全选'
                }
              )
            ])
          ])
        ]),

        // 权限树容器
        h(NScrollbar, {
          class: 'flex-1 max-h-[60vh]',
          themeOverrides: scrollbarInMainLayout.value
        }, [
          h('div', { class: 'p-4' }, [
            isLoadingPermissions.value ? h(
              'div', { class: 'flex items-center justify-center h-48' }, [
                h(NSpace, { vertical: true, align: 'center' }, [
                  h(NSpin, { size: 'large' }),
                  h('span', { class: 'text-gray-500 dark:text-gray-400 mt-2' }, '加载权限数据中...')
                ])
              ]
            ) : filteredTreeData.value.length > 0 ? h(NTree, {
              blockLine: true,
              checkable: true,
              defaultExpandAll: true,
              size: 'large',
              checkedKeys: checkedKeys.value,
              'onUpdate:checkedKeys': (value: string[]) => {
                checkedKeys.value = value
              },
              data: filteredTreeData.value,
              disabled: isLoadingPermissions.value,
              class: 'permission-tree'
            }) : h(
              'div', { class: 'flex flex-col items-center justify-center h-48 text-center p-4' }, [
                h('div', { class: 'w-12 h-12 bg-gray-200 dark:bg-gray-700 rounded-full flex items-center justify-center mb-3' }, [
                  h('span', { class: 'iconify ph--folder-open text-2xl text-gray-400 dark:text-gray-500' })
                ]),
                h('h4', { class: 'text-base font-medium mb-1' }, '未找到权限'),
                h('p', { class: 'text-sm text-gray-500 dark:text-gray-400' }, searchKeyword.value ? '没有匹配的权限数据' : '当前没有可用的权限')
              ]
            )
          ])
        ])
      ])
    },
    onPositiveClick: async () => {
      try {
        await roleApi.assignPermissions(assignPermissionRoleId.value, checkedKeys.value)
        message.success('权限分配成功')
        getDataList()
        modal.destroyAll()
        isLoadingPermissions.value = false
      } catch (error) {
        console.error('权限分配失败:', error)
        message.error('权限分配失败，请重试')
        isLoadingPermissions.value = false
      }
    },
    onNegativeClick: () => {
      modal.destroyAll()
      isLoadingPermissions.value = false
      searchKeyword.value = '' // 重置搜索关键词
    },
  })
}

// 渲染权限数量
function renderPermissionCount(permissionIds: string[]) {
  return h(
    NTag,
    {
      type: 'info',
      bordered: false,
      size: 'small',
    },
    `${permissionIds.length} 个权限`,
  )
}

// 渲染操作按钮
const renderActions = (row: Role) => {
  const actions = []

  // 编辑按钮
  actions.push(
    h(
      NButton,
      {
        secondary: true,
        type: 'primary',
        size: 'small',
        onClick: () => openModal(row),
      },
      {
        icon: () => h('span', { class: 'iconify ph--pencil' }),
        default: () => '编辑',
      },
    ),
  )

  // 分配权限按钮
  actions.push(
    h(
      NButton,
      {
        secondary: true,
        type: 'success',
        size: 'small',
        onClick: () => assignPermissionHandler(row.id, row.name),
      },
      {
        icon: () => h('span', { class: 'iconify ph--key' }),
        default: () => '分配权限',
      },
    ),
  )

  // 删除按钮
  actions.push(
    h(
      NPopconfirm,
      {
        positiveText: '确定',
        negativeText: '取消',
        onPositiveClick: () => deleteRoleHandler(row.id),
      },
      {
        trigger: () => {
          return h(
            NButton,
            {
              secondary: true,
              type: 'error',
              size: 'small',
            },
            {
              icon: () => h('span', { class: 'iconify ph--trash' }),
              default: () => '删除',
            },
          )
        },
        default: () => '确认删除吗？',
      },
    ),
  )

  return actions
}

// 表格列配置
const columns = computed<DataTableColumns<Role>>(() => {
  // 基础列配置 - 小屏幕下显示的核心列
  const baseColumns: DataTableColumns<Role> = [
    {
      type: 'selection',
      options: ['all', 'none'],
    },
    {
      key: 'name',
      title: '角色名称',
      ellipsis: true,
    },
    {
      key: 'actions',
      title: '',
      width: isActionsExpanded.value ? 300 : 0,
      fixed: 'right',
      render: (row: Role) => {
        return h('div', { class: 'flex gap-2 items-center p-2' }, [
          // 只有当展开时才显示操作按钮
          ...(isActionsExpanded.value ? renderActions(row) : []),
        ])
      },
    },
  ]

  // 中屏幕及以上添加更多列
  if (!isMaxMd.value) {
    baseColumns.splice(2, 0, {
      key: 'permissions',
      title: '权限数量',
      render: (row: Role) => {
        return h('span', renderPermissionCount(row.permissions))
      },
    })
  }

  // 大屏幕添加完整列
  if (!isMaxLg.value) {
    baseColumns.splice(3, 0, {
      key: 'description',
      title: '角色描述',
      ellipsis: true,
    })
    baseColumns.splice(4, 0, {
      key: 'createdAt',
      title: '创建时间',
      render: (row: Role) => {
        return h('span', new Date(row.createdAt).toLocaleString())
      },
    })
    baseColumns.splice(5, 0, {
      key: 'updatedAt',
      title: '更新时间',
      render: (row: Role) => {
        return h('span', new Date(row.updatedAt).toLocaleString())
      },
    })
  }

  return baseColumns
})


// 获取所有可见节点的key
function getAllVisibleKeys(tree: TreeData[]): string[] {
  return tree.reduce((keys, item) => {
    keys.push(item.key)
    if (item.children) {
      keys.push(...getAllVisibleKeys(item.children))
    }
    return keys
  }, [] as string[])
}

// 判断是否所有可见节点都已选中
const isAllSelected = computed(() => {
  const visibleKeys = getAllVisibleKeys(filteredTreeData.value)
  if (visibleKeys.length === 0) return false
  // 检查所有可见节点的key是否都在checkedKeys中
  return visibleKeys.every(key => checkedKeys.value.includes(key))
})

// 切换全选/取消全选
async function toggleSelectAll() {
  const visibleKeys = getAllVisibleKeys(filteredTreeData.value)
  if (isAllSelected.value) {
    // 取消全选
    checkedKeys.value = checkedKeys.value.filter(key => !visibleKeys.includes(key))
  } else {
    // 全选
    checkedKeys.value = Array.from(new Set([...checkedKeys.value, ...visibleKeys]))
  }
}

// 统计数据展示
const statCards = [
  {
    title: '总角色数',
    value: roleStats.total,
    type: 'total',
    icon: 'iconify ph--users',
    color: '#3b82f6',
  },
  {
    title: '已分配权限',
    value: roleStats.withPermissions,
    type: 'withPermissions',
    icon: 'iconify ph--check-circle',
    color: '#10b981',
  },
  {
    title: '未分配权限',
    value: roleStats.withoutPermissions,
    type: 'withoutPermissions',
    icon: 'iconify ph--x-circle',
    color: '#ef4444',
  },
]

// 重置搜索表单
function resetSearchForm() {
  searchForm.keyword = ''
  getDataList()
}

// 初始化数据
async function initData() {
  await getPermissionList()
  await getDataList()
}

initData()
</script>

<template>
  <ScrollContainer
    wrapper-class="flex flex-col gap-y-4"
    :scrollable="isMaxLg"
  >
    <!-- 统计卡片 -->
    <div class="grid grid-cols-1 gap-4 md:grid-cols-3">
      <NCard
        v-for="card in statCards"
        :key="card.type"
        size="small"
        class="transition-all hover:shadow-md"
      >
        <div class="flex items-center justify-between">
          <div>
            <h3 class="text-sm font-medium text-neutral-500 dark:text-neutral-400">
              {{ card.title }}
            </h3>
            <div class="mt-1 flex items-baseline gap-2">
              <NNumberAnimation
                :from="0"
                :to="card.value"
                :duration="1000"
                class="text-2xl font-semibold"
                :class="{
                  'text-blue-500': card.type === 'total',
                  'text-green-500': card.type === 'withPermissions',
                  'text-red-500': card.type === 'withoutPermissions',
                }"
              />
              <span class="text-sm text-neutral-500 dark:text-neutral-400">个</span>
            </div>
          </div>
          <div
            :class="`flex size-10 items-center justify-center rounded-full text-white`"
            :style="{ backgroundColor: card.color }"
          >
            <span
              :class="card.icon"
              class="text-xl"
            ></span>
          </div>
        </div>
      </NCard>
    </div>

    <!-- 角色管理表格 -->
    <NCard
      :size="isMaxMd ? 'small' : undefined"
      class="flex-1"
      content-class="flex flex-col"
    >
      <!-- 工具栏 -->
      <div
        class="mb-4 flex flex-nowrap items-center justify-between gap-x-4 gap-y-2 overflow-x-auto"
      >
        <!-- 搜索表单 -->
        <div class="flex items-center gap-2">
          <NInput
            v-model:value="searchForm.keyword"
            clearable
            placeholder="角色名称/代码"
            @keyup.enter="getDataList"
            class="w-64"
          />
          <NButton
            type="info"
            @click="getDataList"
            :loading="isRequestLoading"
          >
            <template #icon>
              <span class="iconify ph--magnifying-glass"></span>
            </template>
            查询
          </NButton>
          <NButton
            type="warning"
            @click="resetSearchForm"
          >
            <template #icon>
              <span class="iconify ph--arrow-clockwise"></span>
            </template>
            重置
          </NButton>
        </div>

        <div class="flex items-center gap-x-4 self-center">
          <NButton
            type="primary"
            @click="openModal()"
          >
            <template #icon>
              <span class="iconify ph--plus-circle"></span>
            </template>
            新增角色
          </NButton>
          <NButton
            type="error"
            :disabled="checkedRowKeys.length === 0"
            @click="batchDeleteHandler"
          >
            <template #icon>
              <span class="iconify ph--trash"></span>
            </template>
            批量删除 ({{ checkedRowKeys.length }})
          </NButton>
          <NButton
            type="default"
            size="small"
            @click="isActionsExpanded = !isActionsExpanded"
            class="transition-all duration-300"
            :hidden="dataList.length === 0 && !isRequestLoading"
          >
            <template #icon>
              <span
                class="iconify transition-transform duration-300"
                :class="isActionsExpanded ? 'ph--caret-right' : 'ph--caret-left'"
              />
            </template>
          </NButton>
        </div>
      </div>

      <!-- 数据表格 -->
      <div class="flex flex-1 flex-col">
        <DynamicList
          class="flex-1"
          v-model:checked-row-keys="checkedRowKeys"
          :remote="true"
          :flex-height="!isMaxLg"
          :scroll-x="1800"
          :columns="columns"
          :data="dataList"
          :row-key="(row) => row.id"
          :loading="isRequestLoading"
          :striped="true"
          :page="pagination.page"
          :page-size="pagination.pageSize"
          :item-count="pagination.itemCount"
          :show-size-picker="pagination.showSizePicker"
          :show-quick-jumper="pagination.showQuickJumper"
          :page-sizes="pagination.pageSizes"
          @update:page="(page: number) => {
            pagination.page = page
            getDataList()
          }"
          @update:page-size="(pageSize: number) => {
            pagination.pageSize = pageSize
            pagination.page = 1
            getDataList()
          }"
        />
      </div>
    </NCard>
  </ScrollContainer>
</template>

